/*
 * @Author       : Bing Chen chenbing@iocharger.com
 * @Date         : 2025-01-21 16:09:28
 * @LastEditors  : Bing Chen chenbing@iocharger.com
 * @LastEditTime : 2025-03-15 13:07:00
 * @FilePath     : \openchaoji-corelib\x86\hal_compile_share_x86.c
 * @Description  :
 *
 * Copyright (c) 2025 OpenChaoJi
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the icense for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "OpenChaoJi_shared.h"
#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <string.h>
#include <libgen.h> // For basename
#include <sys/time.h> // For gettimeofday
#include <ctype.h>

/**
 * @brief: 获取当前系统已运行的时间, 单位毫秒ms
 * @return 已运行时间
 */
uint32_t OpenChaoJi_os_get_ticks()
{	static long s_first = 0;

    struct timespec tv;
	clock_gettime(CLOCK_MONOTONIC, &tv);
	long diff = (tv.tv_sec * 1000) + (tv.tv_nsec / 1000000);

	if (s_first == 0)
	{
		s_first = diff;
	}

    //CHARGER_DEBUG_KEYI(("diff: %ld \n", diff));
	return diff - s_first;
}

/**
 * @brief: 获取系统当前UTC日期时间, 原则上系统的计时应当使用ticks, 这个time仅用于报文需要互相传递实际时间戳
 * @return UTC时间戳
 */
time_t OpenChaoJi_os_get_time()
{
    return time(NULL);
}

// 全局变量用于存储当前的LOG等级，初始化为默认等级
static int s_debug_level = DEFAULT_DBG_LEVEL;

/**
 * @brief  设置LOG打印水平
 * @param  level: 打印级别-8个打印级别的或结果, 表示是否打开某个级别
 */
void OpenChaoJi_debug_set_log_level(int level)
{
    if (s_debug_level != level)
    {
        s_debug_level = level;

        char tmp[100];

        strcpy(tmp, "DBG LEVEL:");
        strcat(tmp, ((level & DBGL_DEBUG)   != 0) ? " DEBUG" : "");
        strcat(tmp, ((level & DBGL_INFO)    != 0) ? " INFO" : "");
        strcat(tmp, ((level & DBGL_NOTICE)  != 0) ? " NOTICE" : "");
        strcat(tmp, ((level & DBGL_WARNING) != 0) ? " WARNING" : "");
        strcat(tmp, ((level & DBGL_ERR)     != 0) ? " ERR" : "");
        strcat(tmp, ((level & DBGL_ALERT)   != 0) ? " ALERT" : "");
        strcat(tmp, ((level & DBGL_EMERG)   != 0) ? " EMERG" : "");

        LOG_EMERG("%s", tmp);
    }

	return;
}

/**
 * @brief  获取LOG打印水平
 * @return level: 打印级别-8个打印级别的或结果, 表示是否打开某个级别
 */
int OpenChaoJi_debug_get_log_level()
{
    return s_debug_level;
}

static void OpenChaoJi_debug_print_header(char* filename, int line, int mask)
{
// Get the current timestamp with milliseconds
    struct timeval tv;
    gettimeofday(&tv, NULL);
    struct tm *time_info = localtime(&tv.tv_sec);

    char time_str[24]; // Format: YYYY-MM-DD HH:MM:SS.mmm
#if 0
    strftime(time_str, sizeof(time_str), "%Y-%m-%d %H:%M:%S", time_info);
#else
    strftime(time_str, sizeof(time_str), "%H:%M:%S", time_info);
#endif

    if (filename == NULL)
    {
        fprintf(stdout, "[%s.%03ld] ", time_str, tv.tv_usec / 1000);
    }
    else
    {
        fprintf(stdout, "[%s.%03ld %s:%d] ", time_str, tv.tv_usec / 1000, basename(filename), line);
    }

    if (mask == DBGL_DEBUG)
    {
        fprintf(stdout, COLOR_DEBUG);
    }
    else if (mask == DBGL_INFO)
    {
        fprintf(stdout, COLOR_INFO);
    }
    else if (mask == DBGL_NOTICE)
    {
        fprintf(stdout, COLOR_NOTICE);
    }
    else if (mask == DBGL_WARNING)
    {
        fprintf(stdout, COLOR_WARNING);
    }
    else if (mask == DBGL_ERR)
    {
        fprintf(stdout, COLOR_ERR);
    }
    else if (mask == DBGL_CRIT)
    {
        fprintf(stdout, COLOR_CRIT);
    }
    else if (mask == DBGL_ALERT)
    {
        fprintf(stdout, COLOR_ALERT);
    }
    else if (mask == DBGL_EMERG)
    {
        fprintf(stdout, COLOR_EMERG);
    }

}

void OpenChaoJi_debug_print_msg_info(char* filename, int line, int mask, const char *format, ...)
{
    if ((mask & s_debug_level) == 0)
    {
        return;
    }

    OpenChaoJi_debug_print_header(filename, line, mask);

    va_list args;
    va_start(args, format);
    vfprintf(stdout, format, args);
    va_end(args);

    fprintf(stdout, "\n" COLOR_RESET);

    fflush(stdout);
}

/**
 * @brief  数据打印
 * @param  data: 打印数据起始地址
 * @param  len: 打印数据长度
 */
void OpenChaoJi_debug_print_buff(char* filename, int line, int mask, const uint8_t * data, int len)
{
    if (data == NULL || len == 0)
    {
        return;
    }

    if ((mask & s_debug_level) == 0)
    {
        return;
    }

    OpenChaoJi_debug_print_header(filename, line, mask);

    fprintf(stdout, "\n");
    // fprintf(stdout, "          0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F  0123456789ABCDEF\n");

    uint8_t lineVal[16];
    int left = len;
    unsigned long line_count = 0;
    int i;
    while (left > 0)
    {
        memset(lineVal, 0x00, 16);

        int copy = 16;
        if (left < 16)
        {
            copy = left;
        }

        memcpy(lineVal, data + (len - left), copy);
        left -= copy;
        line_count++;

        // 每16个字节换行，并打印偏移量
        fprintf(stdout, "%08lx: ", line_count);

        // 打印十六进制值，两个字符一个空格
        for (i = 0; i < 16; i++)
        {
            if (i < copy)
            {
                fprintf(stdout, "%02x ", lineVal[i]);
            }
            else
            {
                fprintf(stdout, "   ");
            }
        }

        // // 每16个字节后换行，并打印对应的ASCII字符（可打印字符）
        // for (i = 0; i < 16; i++)
        // {
        //     if (i < copy)
        //     {
        //         if (isprint(lineVal[i])) {
        //             fprintf(stdout, "%c", lineVal[i]);
        //         } else {
        //             fprintf(stdout, ".");
        //         }
        //     }
        //     else
        //     {
        //         fprintf(stdout, " ");
        //     }
        // }

        fprintf(stdout, "\n");
    }

    fprintf(stdout, COLOR_RESET);

    fflush(stdout);

    return;
}